/*************************************************************************************************
 * Class to represent a robot. A robot can move on the ground in 4 straight directions- right, left
 * forward and backward. The robot can pick up a geometric element if the geometric element's area 
 * fits to the robot's basket. 
 *************************************************************************************************/

package robot;
import geometricElement.GeometricElement;
import ground.GroundObject;

public class Robot extends GroundObject {
	
	// members
	
	private static final int INIT_PACE_NUM = 0; // start counting paces from 0
	private double basket; // used to pick up geometric elements
	private double realDistanceCounter; // keeps track of the real distance the robot passes
	private int paceCounter; // counts each pace that robot makes
	
	// methods

	/**
	 * Creates a new robot with given values
	 * @param xCord initial robot position (x-axis)
	 * @param yCord initial robot position (y-axis)
	 * @param basketCpacity the robot's maximal basket capacity
	 */
	public Robot(int xCord, int yCord, double basketCpacity) {
		// set members as given values
		super(xCord, yCord);
		basket = basketCpacity;
		// initialize distance counters to default initial value
		realDistanceCounter = INIT_PACE_NUM;
		paceCounter = INIT_PACE_NUM;
	}
		
	public boolean canPickElement(GeometricElement elementToPick) {
		if (basket < elementToPick.getArea()) {
			return false;
		}
		
		return true;
	}
	
	/**
	 * Calculates distance from robot to destination as sum of horizontal and vertical distances  
	 * @param xDest- x axis position of destination
	 * @param yDest- y axis position of destination
	 * @return Robot's distance from destination
	 */
	public int calculateDisTanceFromDot(int xDest, int yDest) {
		// real distance = |xDest-x| + |yDest-y|
		return Math.abs(xDest-getXcord()) + Math.abs(yDest-getYcord());
	}

	/**
	 * Gets a position on ground and calculate the real distance between the robot and given position.
	 * Real distance is calculated according to Pythagorean Theorem
	 * @param xDest
	 * @param yDest
	 * @return
	 */
	public double calculateRealDisTanceFromDot(int xDest, int yDest) {
		// distance^2 = (xDest-x)^2 + (yDest-y)^2
		return Math.sqrt( (xDest-getXcord())*(xDest-getXcord()) + (yDest-getYcord())*(yDest-getYcord()) );
	}
	
	/**
	 * Gets the area and position of a geometric element. If the area is too big for robot's basket, the element is
	 * not picked. Otherwise, the real distance between the robot and the element is added to matching counter, pace
	 * counter is incremented with the number of paces the robot needs to get to the element and element's area is
	 * removed from robots basket
	 * @param elmntArea- area of geometric element to be picked
	 * @param xCordElmnt- x-axis coordinate of geometric element to be picked
	 * @param yCordElmnt- y-axis coordinate of geometric element to be picked 
	 * @throws ElementTooBigException- thrown if given area is too big for robot's basket
	 */
	public void pickElement(double elmntArea, int xCordElmnt, int yCordElmnt) throws ElementTooBigException {
		// check if the element exceeds basket's capacity
		if (elmntArea > basket) {
			throw new ElementTooBigException(elmntArea, basket);
		}
		
		// add real distance to the matching counter
		realDistanceCounter += calculateRealDisTanceFromDot(xCordElmnt, yCordElmnt); 
		// count paces to the element
		paceCounter += calculateDisTanceFromDot(xCordElmnt, yCordElmnt);
		// update robot's position
		setXcord(xCordElmnt);
		setYcord(yCordElmnt);
		// pick up the element
		basket -= elmntArea;
	}
	
	/**
	 * Returns robot's printing format. The format includes the following details:
	 * robot's position, real distance the robot passed, number of paces the robot has made and capacity left in its basket 
	 * @return
	 */
	public String toString() {
		return String.format("Position: (%d, %d), Real distance passed: %f, Actual number of paces: %d, Basket capacity left: %f", getXcord(), getYcord(), realDistanceCounter,paceCounter, basket);
	}
}